package CalendarProgram;


/*Contents of CalendarProgran.class */

//Import packages
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class CalendarProgram {
	static JLabel lblMonth, lblYear, lblWeek;
	static JButton btnPrevMonth, btnNextMonth, btnPrevWeek, btnNextWeek;
	static JTable tblCalendar;
	static JComboBox cmbYear;
	static JFrame frmMain;
	static Container pane;
	static DefaultTableModel mtblCalendar; //Table model
	static JScrollPane stblCalendar; //The scrollpane
	static JPanel pnlCalendar;
	static int realYear, realMonth, realWeek, realDay, currentYear, currentMonth, currentWeek;

	public static void main (String args[]){
		//Look and feel
		try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
		catch (ClassNotFoundException e) {}
		catch (InstantiationException e) {}
		catch (IllegalAccessException e) {}
		catch (UnsupportedLookAndFeelException e) {}

		//Prepare frame
		frmMain = new JFrame ("SunTime"); //Create frame
		frmMain.setSize(330, 442); //Set size to 400x400 pixels
		pane = frmMain.getContentPane(); //Get content pane
		pane.setLayout(null); //Apply null layout
		frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Close when X is clicked

		//Create controls
		lblMonth = new JLabel ("January");
		lblYear = new JLabel ("Change year:");
		lblWeek = new JLabel("Week 1");
		cmbYear = new JComboBox();
		btnPrevMonth = new JButton ("<<");
		btnNextMonth = new JButton (">>");
		btnPrevWeek = new JButton ("<<");
		btnNextWeek = new JButton (">>");
		mtblCalendar = new DefaultTableModel(){public boolean isCellEditable(int rowIndex, int mColIndex){return false;}};
		tblCalendar = new JTable(mtblCalendar);
		stblCalendar = new JScrollPane(tblCalendar);
		pnlCalendar = new JPanel(null);

		//Set border
		pnlCalendar.setBorder(BorderFactory.createTitledBorder("Calendar"));
		
		//Register action listeners
		btnPrevMonth.addActionListener(new btnPrevMonth_Action());
		btnNextMonth.addActionListener(new btnNextMonth_Action());
		btnPrevWeek.addActionListener(new btnPrevWeek_Action());
		btnNextWeek.addActionListener(new btnNextWeek_Action());
		cmbYear.addActionListener(new cmbYear_Action());
		
		//Add controls to pane
		pane.add(pnlCalendar);
		pnlCalendar.add(lblWeek);
		pnlCalendar.add(lblMonth);
		pnlCalendar.add(lblYear);
		pnlCalendar.add(cmbYear);
		pnlCalendar.add(btnPrevMonth);
		pnlCalendar.add(btnNextMonth);
		pnlCalendar.add(btnPrevWeek);
		pnlCalendar.add(btnNextWeek);
		pnlCalendar.add(stblCalendar);
		
		//Set bounds
		pnlCalendar.setBounds(0, 0, 320, 411);
		lblWeek.setBounds(160-lblWeek.getPreferredSize().width/2, 75, 100, 25);
		lblMonth.setBounds(160-lblMonth.getPreferredSize().width/2, 25, 100, 25);
		lblYear.setBounds(10, 380, 80, 20);
		cmbYear.setBounds(230, 380, 80, 20);
		btnPrevMonth.setBounds(10, 25, 50, 25);
		btnNextMonth.setBounds(260, 25, 50, 25);
		btnPrevWeek.setBounds(10, 75, 50, 25);
		btnNextWeek.setBounds(260, 75, 50, 25);
		stblCalendar.setBounds(10, 119, 300, 250);
		
		//Make frame visible
		frmMain.setResizable(false);
		frmMain.setVisible(true);
		
		//Get real month/year
		GregorianCalendar cal = new GregorianCalendar(); //Create calendar
		cal.setMinimalDaysInFirstWeek(1);
		realDay = cal.get(GregorianCalendar.DAY_OF_MONTH); //Get day
		realWeek = cal.get(GregorianCalendar.WEEK_OF_MONTH); //Get week of the month
		realMonth = cal.get(GregorianCalendar.MONTH); //Get month
		realYear = cal.get(GregorianCalendar.YEAR); //Get year
		currentMonth = realMonth; //Match month and year
		currentYear = realYear;
		
		//Add headers
		String[] headers = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; //All headers
		for (int i=0; i<7; i++){
			mtblCalendar.addColumn(headers[i]);
		}
		
		tblCalendar.getParent().setBackground(tblCalendar.getBackground()); //Set background

		//No resize/reorder
		tblCalendar.getTableHeader().setResizingAllowed(false);
		tblCalendar.getTableHeader().setReorderingAllowed(false);

		//Single cell selection
		tblCalendar.setColumnSelectionAllowed(true);
		tblCalendar.setRowSelectionAllowed(true);
		tblCalendar.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		//Set row/column count
		tblCalendar.setRowHeight(38);
		mtblCalendar.setColumnCount(7);
		mtblCalendar.setRowCount(6);
		
		//Populate table
		for (int i=realYear-100; i<=realYear+100; i++){
			cmbYear.addItem(String.valueOf(i));
		}
		
		//Refresh calendar
		refreshCalendar (realMonth, realYear, realWeek); //Refresh calendar
	}
	
	public static void refreshCalendar(int month, int year, int week){
		//Variables
		String[] months =  {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
		String[] weeks =  {"Week 1", "Week 2", "Week 3", "Week 4", "Week 5", "Week 6"};
		int nod, som, now; //Number Of Days, Start Of Month, Number Of Weeks (in a month)
		
		//Get first day of month and number of days
				GregorianCalendar cal = new GregorianCalendar(year, month, 1);
				cal.setMinimalDaysInFirstWeek(1);
				nod = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
				som = cal.get(GregorianCalendar.DAY_OF_WEEK);
				now = cal.getActualMaximum(GregorianCalendar.WEEK_OF_MONTH)-1;
		
		//Allow/disallow buttons
		btnPrevMonth.setEnabled(true);
		btnNextMonth.setEnabled(true);
		btnPrevWeek.setEnabled(true);
		btnNextWeek.setEnabled(true);
		if (month == 0 && year <= realYear-10){btnPrevMonth.setEnabled(false);} //Too early
		if (month == 11 && year >= realYear+100){btnNextMonth.setEnabled(false);} //Too late
		if (week == 0 && month == 0 && year <= realYear-10){btnPrevWeek.setEnabled(false);} //Too early
		if (week == now && month == 11 && year >= realYear+100){btnNextWeek.setEnabled(false);} //Too late
		lblMonth.setText(months[month]); //Refresh the month label (at the top)
		lblMonth.setBounds(160-lblMonth.getPreferredSize().width/2, 25, 180, 25); //Re-align label with calendar
		lblWeek.setText(weeks[week]); //Refresh the week label (at the top)
		lblWeek.setBounds(160-lblWeek.getPreferredSize().width/2, 75, 180, 25); //Re-align label with calendar		
		cmbYear.setSelectedItem(String.valueOf(year)); //Select the correct year in the combo box
		
		//Clear table
		for (int i=0; i<6; i++){
			for (int j=0; j<7; j++){
				mtblCalendar.setValueAt(null, i, j);
			}
		}
		
		//Draw calendar
		for (int i=1; i<=(8-som); i++){
			int row = new Integer((i+som-2)/7);
			int column  =  (i+som-2)%7;
			mtblCalendar.setValueAt(i, row, column);
		}

		//Apply renderers
		tblCalendar.setDefaultRenderer(tblCalendar.getColumnClass(0), new tblCalendarRenderer());
	}

	static class tblCalendarRenderer extends DefaultTableCellRenderer{
		public Component getTableCellRendererComponent (JTable table, Object value, boolean selected, boolean focused, int row, int column){
			super.getTableCellRendererComponent(table, value, selected, focused, row, column);
			if (column == 0 || column == 6){ //Week-end
				setBackground(new Color(255, 220, 220));
			}
			else{ //Week
				setBackground(new Color(255, 255, 255));
			}
			if (value != null){
				if (Integer.parseInt(value.toString()) == realDay && currentMonth == realMonth && currentYear == realYear){ //Today
					setBackground(new Color(220, 220, 255));
				}
			}
			setBorder(null);
			setForeground(Color.black);
			return this;  
		}
	}

	static class btnPrevMonth_Action implements ActionListener{
		public void actionPerformed (ActionEvent e){
			if (currentMonth == 0){ //Back one year
				currentMonth = 11;
				currentYear -= 1;
			}
			else{ //Back one month
				currentMonth -= 1;
			}
			refreshCalendar(currentMonth, currentYear, currentWeek);
		}
	}
	static class btnNextMonth_Action implements ActionListener{
		public void actionPerformed (ActionEvent e){
			if (currentMonth == 11){ //Foward one year
				currentMonth = 0;
				currentYear += 1;
			}
			else{ //Foward one month
				currentMonth += 1;
			}
			refreshCalendar(currentMonth, currentYear, currentWeek);
		}
	}
	
	static class btnPrevWeek_Action implements ActionListener{
		public void actionPerformed (ActionEvent e){
			if (currentWeek == 0)
			{ //Back one month
				currentMonth -= 1;
				GregorianCalendar cal = new GregorianCalendar(currentYear, currentMonth, 1);
				cal.setMinimalDaysInFirstWeek(1);
				currentWeek = cal.getActualMaximum(GregorianCalendar.WEEK_OF_MONTH)-1;
			}
			else{ //Back one month
				currentWeek -= 1;
			}
			refreshCalendar(currentMonth, currentYear, currentWeek);
		}
	}
	static class btnNextWeek_Action implements ActionListener{
		public void actionPerformed (ActionEvent e)
		{
			GregorianCalendar cal = new GregorianCalendar(currentYear, currentMonth, 1);
			cal.setMinimalDaysInFirstWeek(1);
			int now = cal.getActualMaximum(GregorianCalendar.WEEK_OF_MONTH)-1;
			if (currentWeek == now){ //Foward one month
				currentWeek = 0;
				currentMonth += 1;
			}
			else{ //Foward one month
				currentWeek += 1;
			}
			refreshCalendar(currentMonth, currentYear, currentWeek);
		}
	}
	static class cmbYear_Action implements ActionListener
	{
		public void actionPerformed (ActionEvent e)
		{
			if (cmbYear.getSelectedItem() != null)
			{
				String b = cmbYear.getSelectedItem().toString();
				currentYear = Integer.parseInt(b);
				refreshCalendar(currentMonth, currentYear, currentWeek);
			}
		}
	}
}

